// Copyright (c) 2023 刻BITTER
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.


#pragma once


#include <Arduino.h>
#include <SPI.h>

#include "oled_basic_init_sequence.hpp"
#include "oled_basic_low_level_common.hpp"

namespace oled_basic {

    template <uint8_t OLED_CS, uint8_t OLED_DC>
    struct ArduinoSpi1316 : public CommonWriteCmdAndData<ArduinoSpi1316<OLED_CS, OLED_DC>>, public Ssd13xxProtocol<ArduinoWire1306<OLED_CS, OLED_DC>> {
        constexpr static size_t init_sequence_length = sizeof(_init_sequence_for_ssd1316_4_wire_spi);
        constexpr static const uint8_t (&init_sequence)[init_sequence_length] = _init_sequence_for_ssd1316_4_wire_spi;


        constexpr static bool manual_start_end_for_data_transfer = false;


        static void write_byte(uint8_t data_byte, write_mode mode) {
            if (mode == write_mode::cmd) {  // DC 拉低表示命令
                digitalWrite(OLED_DC, 0);
            }
            else {
                digitalWrite(OLED_DC, 1);
            }

            // 1.5MHz，MSB first，SCK idle low，sample at rising edge
            SPI.beginTransaction(SPISettings(1.5e6, MSBFIRST, SPI_MODE0));
            digitalWrite(OLED_CS, 0);

            if (mode == write_mode::inverse)
                data_byte = ~data_byte;

            SPI.transfer(data_byte);

            digitalWrite(OLED_CS, 1);
            SPI.endTransaction();
        }
    };


    template <uint8_t OLED_CS, uint8_t OLED_DC>
    struct ArduinoSpi1316_12832 : public ArduinoSpi1316<OLED_CS, OLED_DC> {
        constexpr static uint8_t column_count = 128;
        constexpr static uint8_t page_count = 4;
    };

}  // namespace oled_basic